package com.zz.xdialog

import android.content.Context
import android.content.DialogInterface
import android.os.Build
import android.os.Bundle
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.fragment.app.FragmentManager
import androidx.viewbinding.ViewBinding
import com.zz.xdialog.base.BaseDialogFragment
import com.zz.xdialog.base.XController
import com.zz.xdialog.base.XController.XParams
import com.zz.xdialog.listener.OnBindViewListener

/**
 * Copyright © 2025 zhun All rights reserved.
 * @author: Zha0Zhun 1820022519@qq.com
 * @version: V1.0
 */
open class XDialog : BaseDialogFragment() {
    companion object {
        private const val KEY_XCONTROLLER = "XController"
    }

    protected var xController: XController = XController()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        savedInstanceState?.getParcelable<XParams>(KEY_XCONTROLLER)?.let {
            xController.restoreFromParcelable(it)
        }
    }

    @RequiresApi(Build.VERSION_CODES.P)
    override fun bindView(binding: ViewBinding) {
        binding?.let {
            xController.onBindViewListener?.let { listener ->
                if (listener.javaClass.genericInterfaces.any { it.typeName.contains(xController.viewBindingClass?.simpleName ?: "") }) {
                    (listener as OnBindViewListener<ViewBinding>).onBind(it, this)
                }
            }
        }
    }

    override fun onSaveInstanceState(outState: Bundle) {
        outState.putParcelable(KEY_XCONTROLLER, xController.toParcelable())
        super.onSaveInstanceState(outState)
    }

    override fun onDismiss(dialog: DialogInterface) {
        super.onDismiss(dialog)
        xController.onDismissListener?.onDismiss(dialog)
    }


    override fun getGravity(): Int = xController.gravity

    override fun getDimAmount(): Float = xController.dimAmount

    override fun getDialogHeight(): Int = xController.height

    override fun getDialogWidth(): Int = xController.width

    override fun getFragmentTag(): String = xController.tag

    override fun isCancelableOutside(): Boolean = xController.isCancelableOutside

    override fun getDialogAnimationRes(): Int = xController.dialogAnimationRes
    override fun getViewBindingClass(): Class<out ViewBinding>? = xController.viewBindingClass
    override fun getOnKeyListener(): DialogInterface.OnKeyListener? = xController.onKeyListener

    fun show(): XDialog {
        Log.d(TAG, "show")
        try {
            xController.fragmentManager?.beginTransaction()?.apply {
                add(this@XDialog, xController.tag)
                commitAllowingStateLoss()
            }
        } catch (e: Exception) {
            Log.e("XDialog", e.toString())
        }
        return this
    }

    class Builder(fragmentManager: FragmentManager) {
        private val params = XController.XParams().apply {
            this.fragmentManager = fragmentManager
        }

        fun setViewBinding(clazz: Class<out ViewBinding>) = apply { params.viewBindingClass = clazz }

        fun setWidth(widthPx: Int) = apply { params.width = widthPx }

        fun setHeight(heightPx: Int) = apply { params.height = heightPx }

        fun setScreenWidthAspect(context: Context, widthAspect: Float) = apply {
            params.width = (getScreenWidth(context) * widthAspect).toInt()
        }

        fun setScreenHeightAspect(context: Context, heightAspect: Float) = apply {
            params.height = (getScreenHeight(context) * heightAspect).toInt()
        }

        fun setGravity(gravity: Int) = apply { params.gravity = gravity }

        fun setCancelableOutside(cancel: Boolean) = apply { params.isCancelableOutside = cancel }

        fun setOnDismissListener(listener: DialogInterface.OnDismissListener) = apply {
            params.onDismissListener = listener
        }

        fun setDimAmount(dim: Float) = apply { params.dimAmount = dim }

        fun setTag(tag: String) = apply { params.tag = tag }

        fun <T : ViewBinding> setOnBindViewListener(listener: OnBindViewListener<T>) = apply {
            params.bindViewListener = listener
        }

        fun setDialogAnimationRes(animationRes: Int) = apply {
            params.dialogAnimationRes = animationRes
        }

        fun setOnKeyListener(listener: DialogInterface.OnKeyListener) = apply {
            params.onKeyListener = listener
        }

        fun create(): XDialog {
            return XDialog().apply {
                Log.d(TAG, "create")
                params.apply(xController)
            }
        }

    }
}
